package com.bolt.report.engine.export.html;

import com.bolt.report.definition.PaperSize;
import com.bolt.report.engine.FillElement;
import com.bolt.report.engine.WriterExporterOutput;
import com.bolt.report.engine.export.AbstractExporter;
import com.bolt.report.engine.model.*;
import com.bolt.report.exception.ReportException;
import com.bolt.report.util.StyleUtil;
import com.bolt.report.util.ToolUtil;

import java.io.IOException;
import java.io.Writer;
import java.util.List;
import java.util.Map;

public class HtmlExporter extends AbstractExporter<WriterExporterOutput> {

    protected Writer writer;

    protected int pageIndex;

    protected HtmlExporterVisitor exporterVisitor = new HtmlExporterVisitor();

    public HtmlExporter() {
        super();
    }

    public HtmlExporter(Map<String, Object> parameters) {
        super(parameters);
    }

    @Override
    public void exportReport() throws ReportException {
        initInput();
        writer = getExporterOutput().getWriter();
        try {
            exportReportToWriter();
        } catch (Exception ex) {
            throw new ReportException(ex);
        } finally {
            getExporterOutput().close();
        }
    }

    protected void exportReportToWriter() throws ReportException, IOException {
        exportPage();
    }


    protected void exportPage() throws IOException {
        ColumnHeader columnHeader = reportPrint.getColumnHeader();
        List<PageDetails> pages = reportPrint.getPages();

        if (pages != null && pages.size() > 0) {
            PageRange pageRange = getPageRange();
            int startPageIndex = pageRange.getStartPageIndex();
            int endPageIndex = pageRange.getEndPageIndex();
            PageDetails page = null;
            Title title = reportPrint.getTitle();
            for (pageIndex = startPageIndex; pageIndex <= endPageIndex; pageIndex++) {
                page = pages.get(pageIndex);
                writer.write("<div class=\"bolt-printPaper\" original-height=\"" + reportPrint.getPageHeight(PaperSize.SizeUnit.MM) + "\" style=\"width: " + reportPrint.getPageWidth(PaperSize.SizeUnit.MM) + "mm; height: " + reportPrint.getPageHeight(PaperSize.SizeUnit.MM) + "mm;\">");
                writer.write("<div class=\"bolt-printPaper-content\" style=\"" + StyleUtil.toMarginStyle(reportPrint.getTopMargin(), reportPrint.getLeftMargin(), reportPrint.getBottomMargin(), reportPrint.getRightMargin()) + "\">");
                writer.write("<table  border=\"0\" cellspacing=\"0\" cellpadding=\"0\" style=\"border-collapse:collapse;table-layout:fixed;overflow:visible;width:");
                writer.write(StyleUtil.toSizeUnit(ToolUtil.pixelToPoint(getTableWidth(page))));
                writer.write("\">\n");
                writer.write("\n");
                expColgroup(page.getColumn());
                if (title != null && title.isLoopPrintTitle(pageIndex)) {
                    exportBand(title);
                }

                if (columnHeader != null && columnHeader.isLoopPrintHead(pageIndex)) {
                    exportBand(columnHeader);
                }

                if (page != null) {
                    exportBand(page);
                }
                writer.write("</table>\n");
                writer.write("</div>\n");
                writer.write("</div>\n");
            }
        }
    }

    private void expColgroup(List<Column> columns) throws IOException {
        writer.write("<colgroup>");
        for (int i = 0; i < columns.size(); i++) {
            Column column = columns.get(i);
            writer.write("<col style=\"width:" + StyleUtil.toSizeUnit(ToolUtil.pixelToPoint(column.getWidth())) + ";\" col=\"" + i + "\"></col>");
        }
        writer.write("</colgroup>");
    }

    private void exportBand(BaseBand baseBand) throws IOException {
        Table table = baseBand.getTable();
        List<Column> columns = table.getColumns();
        List<Row> rows = table.getRows();
        if (columns.isEmpty() || rows.isEmpty()) {
            return;
        }
        for (Row row : rows) {
            if (row.isEmpty()) {
                continue;
            }
            writer.write("<tr valign=\"top\" style=\"height:");
            writer.write(StyleUtil.toSizeUnit(ToolUtil.pixelToPoint(row.getRealHeight())));
            writer.write("\">\n");
            for (Column col : columns) {
                if (col.isHide()) {
                    continue;
                }
                Cell cell = row.getCell(col);
                if (cell == null) {
                    continue;
                }
                writer.write("<td  style=\"");
                writer.write(StyleUtil.toStyle(cell.getStyle()));
                writer.write("\"");
                if (cell.getRowSpan() > 0) {
                    if (cell.getColSpan() > 0) {
                        writer.write(" rowspan=\"" + cell.getRowSpan() + "\" colspan=\"" + cell.getColSpan() + "\"");
                    } else {
                        writer.write(" rowspan=\"" + cell.getRowSpan() + "\"");
                    }
                } else {
                    if (cell.getColSpan() > 0) {
                        writer.write(" colspan=\"" + cell.getColSpan() + "\"");
                    }
                }
                writer.write(">");
                FillElement element = cell.getElement();
                element.accept(exporterVisitor,this);

                writer.write("</td>\n");
            }
            writer.write("</tr>\n");
        }
    }

    public Boolean containsParam(String key) {
        return parameters.containsKey(key);
    }
}